Antipattern: Store Password in Plain Text

Let’s explore the risks of using passwords as plain text.

A frequent mistake found in password-recovery solutions is that the application allows the user to request an email containing their password in plain text. This is a dire security flaw related to the database design, and it leads to several security risks that could allow unauthorized people to gain privileged access to the application.

Let’s explore these risks in the following sections. We will assume that our example bug-tracking database has a table Accounts in which each user’s account is stored as a row of the table.

Storing passwords#

A password is typically stored in the Accounts table as a string attribute column:

Creating Accounts table

We can create an account simply by inserting one row and specifying the password as a string literal:

Inserting data into the Accounts table

It’s not secure to store a password in clear text or even to pass it over the network in the clear. If an attacker can read the SQL statement that we use to insert a password, they can also see the password plainly. This is also true for SQL statements that ask a user to change a password or that verify that a given user input matches a stored password. Hackers have several opportunities to steal a password, including the following:

  • Intercepting network packets as the SQL statement is sent from the application client to the database server. This is easier than it sounds; there are free software tools such as Wireshark.

  • Searching SQL query logs on the database server. The attacker needs access to the database server host. Still, assuming they have that, they can access log files that may include a record of SQL statements executed by that database server.

  • Reading data from database backup files on the server or backup media. Some questions we must ask ourselves include: Are our backup media kept safe? Do we erase backup media destructively before they are recycled or disposed of?

Authenticating passwords#

Later, when the user tries to log in, the application compares the user’s input to the password string stored in the database. This comparison is made as plain text since the password itself is stored in plain text. For example, we can use a query like the following to return a 0 (false) or 1 (true), indicating whether the user’s input matches the password in the database:

Retrieving data using the password from the Accounts table

In the previous example, the password the user entered, “opensesame”, is incorrect, and the query returns a zero value.

Like in the earlier section on storing passwords, interpolating the user’s input string into the SQL query in plain text exposes it to discovery by an attacker.

Don’t lump together two different conditions

Sending passwords in email#

Since the password is stored in plain text in the database, retrieving the password in our application is simple:

Retrieving data for account 123 from the Accounts table

Our application can then send the password to a user’s email address on request. Emails like the following are not too uncommon:

Example of Password Recovery Email:

From: daemon
To: bill@example.com
Subject: password request

You requested a reminder of the password for your account “bill”.
Your password is “xyzzy”.

Click the link below to log in to your account:
http://www.example.com/login

Sending an email with the password in plain text is a serious security risk. An email can be intercepted, logged, and stored in multiple ways by hackers. It’s not good enough that we use a secure protocol to view mail or that the sending and receiving mail servers are managed by responsible system administrators. Since email is routed across the Internet, it can be intercepted at other sites. Secure protocols for email aren’t necessarily widespread or under our control.

Synopsis: Readable Passwords
Solution: Store a Salted Hash of the Password
Mark as Completed
Report an Issue